var args        = require('yargs').argv,
    path        = require('path'),
    flip        = require('css-flip'),
    through     = require('through2'),
    gulp        = require('gulp'),
    $           = require('gulp-load-plugins')(),
    gulpsync    = $.sync(gulp),
    PluginError = $.util.PluginError;

// production mode (see build task)
var isProduction = false;
// styles sourcemaps
var useSourceMaps = false;

// if isLocal is true,destRoot must be '..'
//var destRoot = 'D:/Tomcat/apache-tomcat-8.5.20-8982/webapps' + '/ROOT';
var destRoot = 'C:/Users/hiberk/Documents/apache-tomcat-7.0.69/apache-tomcat-7.0.69/webapps/' + '/ROOT';

// ignore everything that begins with underscore
var hidden_files = '**/_*.*';
var ignored_files = '!'+hidden_files;

// MAIN PATHS
var paths = {
    app:     '../app/', 
    styles:  'less/',
    scripts: 'js/',
    view:    '../app/views/',
    page:    '../app/pages',
    i18n:    '../app/i18n/'
}

// VENDOR CONFIG
var vendor = {
    // vendor scripts required to start the app
    base: {
        source: require('./vendor.base.json'),
        dest: '../app/js',
        name: 'base.js'
    },
    // vendor scripts to make the app work. Usually via lazy loading
    app: {
        source: require('./vendor.json'),
        dest: '../vendor'
    }
};


// SOURCES CONFIG 
var source = {
    scripts: [
        paths.scripts + 'app.init.js',
        paths.scripts + 'modules/*.js',
        paths.scripts + 'modules/controllers/*.js',
        paths.scripts + 'modules/controllers/**/*.js',
        paths.scripts + 'modules/directives/*.js',
        paths.scripts + 'modules/services/**/*.js',
        paths.scripts + 'modules/filters/*.js',
        paths.scripts + 'custom/*.js',
        paths.scripts + 'custom/controllers/**/*.js',
        paths.scripts + 'custom/directives/*.js',
        paths.scripts + 'custom/services/**/*.js',
        paths.scripts + 'custom/filters/*.js'
    ],
    templates: {
        index: [paths.markup + 'index.*'],
        views: [paths.markup + '**/*.*', '!' + paths.markup + 'index.*']
    },
    styles: {
        app:    [paths.styles + '*.*'],
        themes: [paths.styles + 'themes/*'],
        watch:  [paths.styles + '**/*', '!' + paths.styles + 'themes/*']
    },
    views: [
        paths.view + '*.html',
        paths.view + '**/*.html'
    ],
    pages: [
        paths.page + '*.html',
        paths.page + '**/*.html'
    ],
    i18ns: [
        paths.i18n + '*.json'
    ]
};

// BUILD TARGET CONFIG 
var build = {
    sApp: '../app/**/*',
    sVendor: '../vendor/**/*',
    dApp: destRoot + '/app',
    dVendor: destRoot + '/vendor',
    scripts: destRoot + '/app/js',
    styles:  destRoot + '/app/css',
    templates: {
        index: '../',
        views: paths.app
    }
};

// PLUGINS OPTIONS

var prettifyOpts = {
    indent_char: ' ',
    indent_size: 3,
    unformatted: ['a', 'sub', 'sup', 'b', 'i', 'u']
};

var vendorUglifyOpts = {
    mangle: {
        except: ['$super'] // rickshaw requires this
    }
};

//---------------
// TASKS
//---------------


// JS APP
gulp.task('scripts:app', function() {
    log('Building scripts..');
    // Minify and copy all JavaScript (except vendor scripts)
    return gulp.src(source.scripts)
        .pipe( $.if( useSourceMaps, $.sourcemaps.init() ))
        .pipe($.concat( 'app.js' ))
        .pipe($.ngAnnotate())
        .on('error', handleError)
        .pipe( $.if(isProduction, $.uglify({preserveComments:'false'}) ))
        .on('error', handleError)
        .pipe( $.if( useSourceMaps, $.sourcemaps.write() ))
        .pipe(gulp.dest(build.scripts))
        .pipe(gulp.dest('../app/js'));
});


// VENDOR BUILD
gulp.task('vendor', gulpsync.sync(['vendor:base', 'vendor:app']) );

// Build the base script to start the application from vendor assets
gulp.task('vendor:base', function() {
    log('Copying base vendor assets..');
    return gulp.src(vendor.base.source)
        .pipe($.expectFile(vendor.base.source))
        .pipe($.if( isProduction, $.uglify() ))
        .pipe($.concat(vendor.base.name))
        .pipe(gulp.dest(vendor.base.dest))
        ;
});

// copy file from bower folder into the app vendor folder
gulp.task('vendor:app', function() {
    log('Copying vendor assets..');

    var jsFilter = $.filter('**/*.js');
    var cssFilter = $.filter('**/*.css');

    return gulp.src(vendor.app.source, {base: 'bower_components'})
        .pipe($.expectFile(vendor.app.source))
        .pipe(jsFilter)
        .pipe($.if( isProduction, $.uglify( vendorUglifyOpts ) ))
        .pipe( gulp.dest(vendor.app.dest) )
        .pipe(jsFilter.restore())
        .pipe(cssFilter)
        .pipe($.if( isProduction, $.minifyCss() ))
        .pipe(cssFilter.restore())
        .pipe( gulp.dest(vendor.app.dest) );

});

// APP LESS
gulp.task('styles:app', function() {
    log('Building application styles..');
    return gulp.src(source.styles.app)
        .pipe( $.if( useSourceMaps, $.sourcemaps.init() ))
        .pipe( $.less() )
        .on('error', handleError)
        .pipe( $.if( isProduction, $.minifyCss() ))
        .pipe( $.if( useSourceMaps, $.sourcemaps.write() ))
        .pipe(gulp.dest(build.styles))
        .pipe(gulp.dest('../app/css'));
});

// LESS THEMES
gulp.task('styles:themes', function() {
    log('Building application theme styles..');
    return gulp.src(source.styles.themes)
        .pipe( $.less() )
        .on('error', handleError)
        .pipe(gulp.dest(build.styles))
        .pipe(gulp.dest('../app/css'));
});

//---------------
// WATCH
//---------------

// Rerun the task when a file changes
gulp.task('watch', function() {
    log('Starting watch and LiveReload..');

    $.livereload.listen();

    gulp.watch(source.scripts,         ['scripts:app']);
    gulp.watch(source.styles.watch,    ['styles:app']);
    gulp.watch(source.styles.themes,   ['styles:themes']);
    gulp.watch(source.views, function(event){
        var index = event.path.indexOf('\\app\\views\\');
        var lastIndex = event.path.lastIndexOf('\\');
        gulp.src(event.path).pipe(gulp.dest(destRoot + event.path.substring(index,lastIndex)));
    });
    gulp.watch(source.i18ns, function(event){
        var index = event.path.indexOf('\\app\\i18n\\');
        var lastIndex = event.path.lastIndexOf('\\');
        gulp.src(event.path).pipe(gulp.dest(destRoot + event.path.substring(index,lastIndex)));
    });

    // a delay before triggering browser reload to ensure everything is compiled
    var livereloadDelay = 1500;
    // list of source file to watch for live reload
    var watchSource = [].concat(
        source.scripts,
        source.styles.watch,
        source.styles.themes,
        source.templates.views,
        source.templates.index,
        source.views,
        source.pages,
        source.i18ns
    );

    gulp.watch(watchSource)
        .on('change', function(event) {
        setTimeout(function() {
            $.livereload.changed( event.path );
        }, livereloadDelay);
        });

});

//---------------
// MAIN TASKS
//---------------

// build for production (minify)
gulp.task('build', gulpsync.sync([
          'prod',
          'vendor',
          'assets',
          'publish'
        ]));

gulp.task('prod', function() { 
  log('Starting production build...');
  isProduction = true; 
});

// build with sourcemaps (no minify)
gulp.task('sourcemaps', ['usesources', 'default']);
gulp.task('usesources', function(){ useSourceMaps = true; });

gulp.task('publish',function(){
    log('Copying to destination..');
    gulp.src('../index.html').pipe(gulp.dest(destRoot));
    gulp.src(build.sApp).pipe(gulp.dest(build.dApp));
    gulp.src(build.sVendor).pipe(gulp.dest(build.dVendor));
})

// default (no minify)
gulp.task('default', gulpsync.sync([
          'vendor',
          'assets',
          'publish',
          'watch'
        ]), function(){

  log('************');
  log('* All Done * You can start editing your code, LiveReload will update your browser after any change..');
  log('************');

});

gulp.task('assets',[
          'scripts:app',
          'styles:app',
          'styles:themes'
        ]);


/////////////////////


// Error handler
function handleError(err) {
  log(err.toString());
  this.emit('end');
}

// log to console using 
function log(msg) {
    $.util.log( $.util.colors.blue( msg ) );  
}
